/*
 * Copiado de hibernate.org
 */
package br.com.ir.tcc.geco.service;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateSession {
	
	/** Read the configuration, will share across threads **/
	private static SessionFactory sessionFactory;
	
	/** the per thread session **/
	private static final ThreadLocal<Session> currentSession = new ThreadLocal<Session>();
	
	/** The constants for describing the ownerships **/
	private static final Owner trueOwner = new Owner(true);
	private static final Owner fakeOwner = new Owner(false);

	/**
	 * get the hibernate session and set it on the thread local. Returns
	 * trueOwner if it actually opens a session
	 */
	public static Object createSession() throws Exception {
		Session session = (Session) currentSession.get();
		System.out.println(session);
		if (session == null) {
			System.out.println("No Session Found - Create and give the identity");
			session = getSessionFactory().openSession();
			currentSession.set(session);
			return trueOwner;
		}
		System.out.println("Session Found - Give a Fake identity");
		return fakeOwner;
	}

	/**
	 * The method for closing a session. The close and flush will be executed
	 * only if the session is actually created by this owner.
	 */
	public static void closeSession(Object ownership) throws Exception {
		if (((Owner) ownership).identity) {
			System.out.println("Identity is accepted. Now closing the session");
			Session session = (Session) currentSession.get();
			session.close();
			currentSession.set(null);
		} else {
			System.out.println("Identity is rejected. Ignoring the request");
		}
	}

	/**
	 * returns the current session
	 */
	public static Session getSession() throws HibernateException {
		return (Session) currentSession.get();
	}

	/**
	 * Creating a session factory , if not already loaded
	 */
	private static SessionFactory getSessionFactory() throws HibernateException {
		try {
			if (sessionFactory == null) {
				sessionFactory =  new AnnotationConfiguration().configure()
						.buildSessionFactory();
			}
			return sessionFactory;
		} catch (Exception e) {
			e.printStackTrace();
			throw new HibernateException("Error getting Factory");
		}
	}

	/**
	 * Internal class , for handling the identity. Hidden for the developers
	 */
	private static class Owner {
		public Owner(boolean identity) {
			this.identity = identity;
		}
		boolean identity = false;
	}
}